package cc.magicjson.example.demo.collection;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.Comparator.comparing;


class DataItem {
	private String timestamp;
	private String data;

	public DataItem(String timestamp, String data) {
		this.timestamp = timestamp;
		this.data = data;
	}

	public String getTimestamp() {
		return timestamp;
	}

	public String getData() {
		return data;
	}

	public void setData(String data) {
		this.data = data;
	}

	@Override
	public String toString() {
		return "DataItem{" +
				"timestamp='" + timestamp + '\'' +
				", data='" + data + '\'' +
				'}';
	}
}

public class MergeDataItems {

	// 示例数据列表1
	private static List<DataItem> list1 = Arrays.asList(
			new DataItem("2023-01-01 10:00", "A"),
			new DataItem("2023-01-01 11:00", "B"),
			new DataItem("2023-01-01 12:00", "C")
	);

	// 示例数据列表2
	private static List<DataItem> list2 = Arrays.asList(
			new DataItem("2023-01-01 10:00", "D"),
			new DataItem("2023-01-01 11:30", "E"),
			new DataItem("2023-01-01 13:00", "F")
	);

	public static void main(String[] args) {
		doMergeListByBiFunction();
	}

	private static void doMergeListByBiFunction() {
		// 按照时间合并两个列表
		List<DataItem> mergedList = mergeAndGroupLists(
				list1,
				list2,
				DataItem::getTimestamp,
				(item1, item2) -> {
					DataItem result = new DataItem(item1.getTimestamp(), item1.getData());
					result.setData(result.getData() + "-" + item2.getData());
					return result;
				}

		);
		System.err.println("================doMergeListByBiFunction================");
		// 输出合并后的列表
		mergedList.forEach(System.err::println);
	}

	public static <T> List<T> mergeAndGroupLists(List<T> sourceList1, List<T> sourceList2,
										 Function<T, Comparable> keyExtractor,
										 BiFunction<T, T, T> elementMerger){
		return mergeAndGroupLists(sourceList1, sourceList2, keyExtractor, keyExtractor, elementMerger);
	}

	/**
	 * 合并两个列表中的元素，根据指定的比较器和分组函数进行分组和合并。
	 *
	 * @param sourceList1 第一个列表
	 * @param sourceList2 第二个列表
	 * @param comparableKeyExtractor 比较器函数，用于比较元素的键值
	 * @param groupKeyExtractor 分组函数，用于分组元素
	 * @param elementMerger 合并函数，用于合并元素
	 * @return 合并后的列表
	 */
	public static <T> List<T> mergeAndGroupLists(List<T> sourceList1, List<T> sourceList2, Function<T, Comparable> comparableKeyExtractor,
										 Function<T, Comparable> groupKeyExtractor,
			BiFunction<T, T, T> elementMerger) {
		// 合并两个列表将分并将组结果转换为Map
		Map<Comparable, List<T>> map = (Map<Comparable, List<T>>) Stream.concat(
						Optional.ofNullable(sourceList1).orElse(Collections.emptyList()).stream(),
						Optional.ofNullable(sourceList2).orElse(Collections.emptyList()).stream())
				// 根据比较器函数进行排序
				.sorted(comparing(comparableKeyExtractor))
				// 根据分组函数进行分组
				.collect(Collectors.groupingBy(groupKeyExtractor));
		// 合并分组结果
		return map.values().stream()
				// 过滤空列表
				.filter(items -> !items.isEmpty())
				// 合并列表中的元素
				.map(items -> items.stream().reduce(elementMerger::apply).orElse(null))
				// 收集结果
				.collect(Collectors.toList());
	}
}